import 'dart:collection';
import 'package:analyzer/dart/element/element.dart' as ele;
import 'route.dart';
import 'package:source_gen/source_gen.dart';
import 'package:build/build.dart';
import 'dart:io';
import 'tpl/tpl.dart' as tpl;

class RouteGenerator extends GeneratorForAnnotation<GRoute> {
  static final separator = Platform.pathSeparator;
  static final Map constantMap = Map();
  static final Map routesMap = Map();
  static final Map importMap = Map();
  static var defaultRoute = "";
  static var debugRoute = "";

  static final RouteGenerator _instance = RouteGenerator._internal();

  factory RouteGenerator() => _instance;

  RouteGenerator._internal();

  String buildConstant(Map map, defaultRoute, debugRoute) {
    var sb = StringBuffer();
    SplayTreeMap st = SplayTreeMap.from(map);
    st.forEach((key, value) {
      if (value == defaultRoute) {
        sb.writeln("  /// 入口页面");
      } else if (value == debugRoute) {
        sb.writeln("  /// debug页面");
      }
      sb.writeln("  static const String $value = '$key';");
    });
    return sb.toString();
  }

  String buildWidgetName(Map map) {
    var sb = StringBuffer();
    SplayTreeMap st = SplayTreeMap.from(map);
    st.forEach((key, value) {
      sb.writeln("    RouteConstant.$value: '$value',");
    });
    return sb.toString();
  }

  String buildRoutes(Map map, defaultRoute) {
    var sb = StringBuffer();
    SplayTreeMap st = SplayTreeMap.from(map);
    st.forEach((key, value) {
      if (key == defaultRoute) {
        sb.writeln("    RouteConstant.$key: (context) {");
        sb.writeln("      ScreenSizeFit.init(context);");
        sb.writeln("      return const $key(title: '$value');");
        sb.writeln("    },");
      } else {
        sb.writeln(
            "    RouteConstant.$key: (context) => const $key(title: '$value'),");
      }
    });
    return sb.toString();
  }

  String buildImport(Map map) {
    var sb = StringBuffer();
    SplayTreeMap st = SplayTreeMap.from(map);
    st.forEach((key, value) {
      sb.writeln("import '$key';");
    });
    return sb.toString();
  }

  @override
  generateForAnnotatedElement(
      ele.Element element, ConstantReader annotation, BuildStep buildStep) {
    // logPrint('start route', level: Level.info);
    var enable = false;
    try {
      enable = annotation.read('enable').boolValue;
    } catch (e) {}
    if (!enable) return null;
    var url, title;
    try {
      url = annotation.read('url').stringValue;
    } catch (e) {}
    try {
      title = annotation.read('title').stringValue;
    } catch (e) {}
    if (url == '/') {
      //入口
      defaultRoute = element.name!;
    } else if (url == '/debug') {
      debugRoute = element.name!;
    }
    constantMap[url] = element.name;
    routesMap[element.name] = title;
    if (buildStep.inputId.path.contains('lib/')) {
      importMap[
              "package:${buildStep.inputId.package}/${buildStep.inputId.path.replaceFirst('lib/', '')}"] =
          null;
    }
    File(
        '${Directory.current.path}${separator}lib${separator}route${separator}main.route.dart')
      ..createSync(recursive: true)
      ..writeAsStringSync(
          tpl.clazzTpl(
              buildConstant:
                  buildConstant(constantMap, defaultRoute, debugRoute),
              buildWidgetName: buildWidgetName(constantMap),
              buildRoutes: buildRoutes(routesMap, defaultRoute),
              buildImport: buildImport(importMap),
              defaultRoute: defaultRoute,
              package: buildStep.inputId.package),
          flush: true);
    return null;
  }
}

Builder routeBuilder(BuilderOptions options) =>
    LibraryBuilder(RouteGenerator(), generatedExtension: ".route.dart");
